package com.imooc.router.asm

import org.gradle.api.DefaultTask
import org.gradle.api.file.Directory
import org.gradle.api.file.RegularFile
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.ListProperty
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileOutputStream
import java.util.jar.JarEntry
import java.util.jar.JarFile
import java.util.jar.JarOutputStream
import java.util.zip.ZipEntry

abstract class RouterTask : DefaultTask() {
    //所有的jar文件输入信息
    @get:InputFiles
    abstract val allJars: ListProperty<RegularFile>

    //所有的class文件输入信息
    @get:InputFiles
    abstract val allDirectories: ListProperty<Directory>

    //经过插桩修改后的输出信息
    @get:OutputFile
    abstract val output: RegularFileProperty

    private val collector: RouterMappingCollector =
        RouterMappingCollector()

    @TaskAction
    fun taskAction() {

        //输出到output的流
        val jarOutput = JarOutputStream(
            BufferedOutputStream(FileOutputStream(output.get().asFile))
        )

        //遍历扫描class
        allDirectories.get().forEach { directory ->
            directory.asFile.walk().forEach { file ->
                if (file.isFile) {
                    if (file.absolutePath.endsWith(".class")) {
                        collector.collect(file)
                    }
                    val relativePath = directory.asFile.toURI().relativize(file.toURI()).path
                    jarOutput.putNextEntry(
                        JarEntry(relativePath.replace(File.separatorChar, '/'))
                    )
                    file.inputStream().use { inputStream ->
                        inputStream.copyTo(jarOutput)
                    }
                    jarOutput.closeEntry()
                }
            }
        }

        //遍历扫描jar
        allJars.get().forEach { jarInputFile ->
            val jarFile = JarFile(jarInputFile.asFile)
            jarFile.entries().iterator().forEach { jarEntry ->
                //过滤掉非class文件，并去除重复无效的META-INF文件
                // 如果不错判断会报错
                if (jarEntry.name.endsWith(".class") && !jarEntry.name.contains("META-INF")) {
                    if(!jarEntry.name.equals("com/imooc/router/mapping/generated/RouterMapping.class")){
                        jarOutput.putNextEntry(JarEntry(jarEntry.name))
                        jarFile.getInputStream(jarEntry).use {
                            it.copyTo(jarOutput)
                        }
                        jarOutput.closeEntry()
                    }
                    if (collector.isMappingJarFile(jarEntry.name)) {
                        collector.collectFromJarFile(jarEntry.name)
                    }
                }
            }
            jarFile.close()
        }
        //对HuiRouterApi进行插桩修改，添加收集到的路由信息
        transformJar(jarOutput)

        //关闭输出流
        jarOutput.close()
    }


    /**
     * 新增目标class
     */
    private fun transformJar(jarOutput: JarOutputStream) {
            val zipEntry = ZipEntry(RouterMappingByteCodeBuilder.CLASS_NAME + ".class")
            jarOutput.putNextEntry(zipEntry)
            jarOutput.write(
                RouterMappingByteCodeBuilder.get(collector.getMappingClassName())
            )
            jarOutput.closeEntry()
    }


}